package collection;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

/**
 * JKD5推出时,推出了一个新的特性:增强型for循环
 * 也称为新循环,使得我们可以使用相同的语法遍历集合或数组.
 */
public class NewForDemo {
    public static void main(String[] args) {
        String[] array = {"one", "two", "three", "four", "five"};
        for (int i = 0; i < array.length; i++) {
            String str = array[i];
            System.out.println(str);
        }
        /*
            增强型for循环语法结构
            for(你要遍历的循环每次会给你一个数,
            所以你要声明一个变量接收:你要遍历的循环){

            }
         */
        /*
            新循环是编译器认可的而非虚拟机,编译器在编译成class文件时会将新循环
            遍历数组改为普通的for循环遍历
         */
        for (String str : array) {
            System.out.println(str);
        }

        /*
        JDK5之后推出的另一个特性:泛型
        泛型也称为参数化类型.让我们可以在使用
        一个类的时候在指定这个类中某个属性或方法参数
        或方法返回值的类型,使得我们使用更灵活
        泛型在集合中广泛使用,用于定义集合中的元素类型.

        泛型是编译器认可的,原型为Object, 当我们使用一个含有泛型定义的类时
        若不指定泛型的实际类型是,那么就使用原型Object.
        实际是用来辅助编译器检查我们在对泛型指定的变量赋值时的类型
        检查工作,检查传入值的类型是否符合泛型要求,不符合编译不通过
        当我们获取泛型类型变量的值时,编译器会辅助进行造型工作.

        集合在定义时,声明一个泛型E
        注:泛型的字符不必非是"E",也不必非要是一个字母,它可以是任意字母与数字的组合
        (数字不能是第一个字符),但通常就使用一个字母表示.
            public interface Collection<E>
         */
        //使用集合时.我们指定E的实际类型为String
        Collection<String> c = new ArrayList();
        /*
            集合的添加元素方法,参数就使用了集合声明的泛型E
            boolean add(E e)
         */
        c.add("一");//调用add方法时,编译器会检查实参类型是否符合E指定的类型
        c.add("二");
        c.add("三");
        c.add("四");
        c.add("五");
        //c.add(1);//一旦传入的实参类型不符合E指定的类型,编译不通过!
        System.out.println(c);

        /*
            集合指定了泛型后,新循环遍历时可以直接用泛型指定的类型变量接收元素

            新循环遍历集合会被编译器改为迭代器方法遍历,因此不要在遍历的过程中通过集合的方法
            增删元素
         */
        for (String str : c) {
            System.out.println(str);
        }
        /*
            使用迭代器时也应当指定泛型，与集合指定的泛型要一致。
         */
        Iterator<String> it = c.iterator();
        while (it.hasNext()){
           /*
                E next(),编译器会在编译时自动补充造型代码,将返回值造型为E
                执行的实际类型.
                下面代码编译后变为:
                String str = (String)it.next();
            */
            String str  = it.next();
            System.out.println(str);
        }

    }
}
